package cn.weiron.fun.sample.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.weiron.fun.infrastructure.auth.Authority;
import cn.weiron.fun.sample.entity.SamplePoint;
import cn.weiron.fun.sample.entity.SamplePointTime;
import cn.weiron.fun.sample.mapper.SamplePointMapper;
import cn.weiron.fun.sample.result.SamplePointResult;
import cn.weiron.fun.sample.service.SamplePointService;
import cn.weiron.fun.sample.service.SamplePointSignService;
import cn.weiron.fun.sample.service.SamplePointTimeService;
import cn.weiron.fun.sample.util.DownloadUtil;
import cn.weiron.fun.sample.util.QRCodeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * (SamplePoint)表服务实现类
 *
 * @author makejava
 * @since 2022-07-16 10:36:17
 */
@Service("samplePointServiceImpl")
@Slf4j
public class SamplePointServiceImpl extends ServiceImpl<SamplePointMapper, SamplePoint> implements SamplePointService {

    @Autowired
    private SamplePointMapper samplePointMapper;

    public SamplePointServiceImpl(@Qualifier("samplePointTimeServiceImpl") SamplePointTimeService timeService
                                 ,@Qualifier("samplePointSignServiceImpl") @Lazy SamplePointSignService signService) {
        this.timeService = timeService;
        this.signService = signService;
    }

    private final SamplePointTimeService timeService;

    private final SamplePointSignService signService;

    @Resource
    private Authority.AccountHandler accountHandler;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SamplePointResult queryById(Integer id) {
        SamplePointResult result = new SamplePointResult();
        SamplePoint samplePoint = samplePointMapper.queryById(id);
        List<SamplePointTime> samplePointTimes = timeService.queryByUniqueId(samplePoint.getUniqueId());
        result.setList(samplePointTimes);
        return result;
    }


    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        //删除的时候要将开放时间段信息一并删除
        SamplePoint samplePoint = samplePointMapper.queryById(id);
        List<SamplePointTime> samplePointTimes = timeService.queryByUniqueId(samplePoint.getUniqueId());
        List<Integer> list = samplePointTimes.stream().map(SamplePointTime::getId).collect(Collectors.toList());
        timeService.removeByIds(list);
        return this.samplePointMapper.deleteById(id) > 0;
    }

    @Override
    public SamplePoint queryByUniqueId(String item) {
        LambdaQueryWrapper<SamplePoint> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SamplePoint::getUniqueId, item);
        return getOne(wrapper);
    }

    @Override
    public void qrCode(HttpServletResponse response, Integer id) {
        String text = id.toString();
        int width = 300;
        int height = 300;
        String format = "jpg";

        Hashtable<EncodeHintType, String> hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");

        BitMatrix bitMatrix = null;

        try {
            bitMatrix = new MultiFormatWriter().encode(text,
                    BarcodeFormat.QR_CODE, width, height, hints);

            // 生成二维码、TODO 部署到网上要重新设置地址
            String pathName = "d:/qrCode/" + File.separator + "qrCode" + id + ".jpg" ;
            File outputFile = new File("d:/qrCode/" + File.separator + "qrCode" + id + ".jpg");

            QRCodeUtil.writeToFile(bitMatrix, format, outputFile);

            /*BufferedImage image = ImageIO.read(outputFile);
            response.setHeader("Cache-Control", "no-store,no-cache");
            response.setContentType("image/jpeg");
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(image, "jpg", out);*/

            if(StringUtils.isBlank(pathName)) {
                log.info("礼包图片路径为空");
                return;
            }
            String imgName = pathName.substring(pathName.lastIndexOf(File.separator) + 1);
            DownloadUtil.downloadFile(response, pathName, imgName);
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void batchGeneration(HttpServletResponse response) {
        LambdaQueryWrapper<SamplePoint> wrapper = Wrappers.lambdaQuery();
        List<SamplePoint> list = list(wrapper);
        List<Integer> ids = list.stream().map(SamplePoint::getId).collect(Collectors.toList());
        //批量生成二維碼
        getCodeZip(response,ids);
    }



    /**
     * 获取二维码压缩包
     *
     * @param response
     * @param ids     二维码字符串列表
     */
    private void getCodeZip(HttpServletResponse response, List<Integer> ids) {
        // 生成二维码图片
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=QrCode-" + System.currentTimeMillis() + ".zip");// 压缩包名
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(response.getOutputStream());
            for (int j = 0; j < ids.size(); j++) {
                String codeString = ids.get(j).toString();
                BufferedImage qrCode = QRCodeUtil.createQrCode(codeString, 900, "JPG");
                InputStream inputStream = bufferedImageToInputStream(qrCode);
                zos.putNextEntry(new ZipEntry(ids.get(j).toString() + ".JPG"));
                int temp = 0;
                while ((temp = inputStream.read()) != -1) {
                    zos.write(temp);
                }
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != zos) {
                    zos.flush();
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 将BufferedImage转换为InputStream
     * @param qrCode
     * @return
     */
    private InputStream bufferedImageToInputStream(BufferedImage qrCode) {

        ByteArrayOutputStream os = new ByteArrayOutputStream();

        InputStream input = null;
        try {
            ImageIO.write(qrCode, "JPG", os);
            input = new ByteArrayInputStream(os.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return input;
    }

}
